package com.transaction.demo.base.biz.impl;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;
import static com.transaction.demo.base.enums.ExceptionEnum.PASSWORD_NOT_CORRECT_ERROR;
import static com.transaction.demo.base.enums.ExceptionEnum.USER_INFO_EXIST_ERROR;
import static com.transaction.demo.base.enums.ExceptionEnum.USER_INFO_NOT_EXIST_ERROR;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.transaction.demo.base.biz.SysRoleBiz;
import com.transaction.demo.base.biz.SysUserBiz;
import com.transaction.demo.base.biz.SysUserRoleBiz;
import com.transaction.demo.base.dao.SysUserDao;
import com.transaction.demo.base.exception.BaseServiceException;
import com.transaction.demo.base.biz.SysMenuBiz;
import com.transaction.demo.base.config.BaseConfig;
import com.transaction.demo.base.entity.SysMenuBean;
import com.transaction.demo.base.entity.SysRoleBean;
import com.transaction.demo.base.entity.SysUserBean;
import com.transaction.demo.base.enums.MenuTypeEnum;
import com.transaction.demo.base.enums.StatusEnum;
import com.transaction.demo.base.utils.BaseConstant;
import com.transaction.demo.base.vo.req.SaveUserRoleListReqVo;
import com.transaction.demo.base.vo.req.SysRoleListReqVo;
import com.transaction.demo.base.vo.req.SysUserAddReqVo;
import com.transaction.demo.base.vo.req.SysUserListReqVo;
import com.transaction.demo.base.vo.req.SysUserReqVo;
import com.transaction.demo.base.vo.req.SysUserRoleAddReqVo;
import com.transaction.demo.base.vo.req.SysUserRoleListReqVo;
import com.transaction.demo.base.vo.req.SysUserUpdateReqVo;
import com.transaction.demo.base.vo.req.UserLoginReqVo;
import com.transaction.demo.base.vo.resp.SysRoleRespVo;
import com.transaction.demo.base.vo.resp.SysUserRespVo;
import com.transaction.demo.base.vo.resp.SysUserRoleRespVo;
import com.transaction.demo.base.vo.resp.UserLoginRespVo;
import com.transaction.demo.base.vo.resp.UserMenuDataVo;
import com.transaction.demo.base.vo.resp.UserMenuResp;
import com.transaction.demo.base.vo.resp.UserRoleResp;
import com.transaction.demo.common.util.ResultPage;

/**
 * 描述：用户信息表
 * 作者：马庆智
 * 日期：2023/03/28 17:07:15
 */
@Slf4j
@Service
public class SysUserBizImpl implements SysUserBiz {

	@Autowired
	private BaseConfig baseConfig;

	@Autowired
	private SysUserDao sysUserDao;

	@Autowired
	private SysUserRoleBiz userRoleBiz;

	@Autowired
	private SysMenuBiz menuBiz;

	@Autowired
	private SysRoleBiz roleBiz;

	/**
	 * 查询用户信息表
	 *
	 * @param sysUser 请求参数
	 * @return SysUserResp
	 * @author 马庆智
	 * @date: 2023/03/28 17:07:15
	 */
	@Override
	public SysUserRespVo querySysUser(SysUserReqVo sysUser) {

		SysUserBean query = sysUserDao.querySysUser(SysUserBean.builder().build());

		return SysUserRespVo.builder().build();
	}

	/**
	 * 查询用户信息表列表
	 *
	 * @param sysUser 请求参数
	 * @return SysUserResp
	 * @author 马庆智
	 * @date: 2023/03/28 17:07:15
	 */
	@Override
	public ResultPage<SysUserRespVo> querySysUserList(SysUserListReqVo sysUser) {

		PageHelper.startPage(sysUser.getCurrent(), sysUser.getPageSize());
		List<SysUserBean> query = sysUserDao.querySysUserList(
				SysUserBean.builder().userName(sysUser.getUserName()).mobileNo(sysUser.getMobileNo())
						.status(sysUser.getStatus()).build());
		PageInfo<SysUserBean> pageInfo = new PageInfo<>(query);

		List<SysUserRespVo> list = pageInfo.getList().stream().map(x -> {
			SysUserRespVo resp = new SysUserRespVo();
			BeanUtils.copyProperties(x, resp);
			return resp;
		}).collect(Collectors.toList());

		return new ResultPage<>(list, pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal());

	}

	/**
	 * 添加用户信息表
	 *
	 * @param addReq 请求参数
	 * @return int
	 * @author 马庆智
	 * @date: 2023/03/28 17:07:15
	 */
	@Override
	public int saveSysUser(SysUserAddReqVo addReq) {
		SysUserBean user = new SysUserBean();
		user.setUserName(addReq.getUserName());
		user.setNickName(addReq.getNickName());
		user.setMobileNo(addReq.getMobileNo());
		user.setPassword(BaseConstant.INITIALIZE_PASSWORD);
		user.setLastLoginDate(new Date());
		user.setErrorCount(0);

		SysUserBean sysUserBean = sysUserDao.querySysUser(user);
		if (sysUserBean != null) {
			log.error("用户信息:{}已存在", addReq);
			throw new BaseServiceException(USER_INFO_EXIST_ERROR);
		}

		BeanUtils.copyProperties(addReq, user);
		user.setCreatedBy("koobe");
		user.setCreatedDate(new Date());

		return sysUserDao.saveSysUser(user);
	}

	/**
	 * 删除用户信息表
	 *
	 * @param ids 请求参数
	 * @return int
	 * @author 马庆智
	 * @date: 2023/03/28 17:07:15
	 */
	@Override
	public int deleteSysUser(String ids) {
		return sysUserDao.deleteSysUser(
				Arrays.stream(ids.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
	}

	/**
	 * 更新用户信息表
	 *
	 * @param updateReq 请求参数
	 * @return int
	 * @author 马庆智
	 * @date: 2023/03/28 17:07:15
	 */
	@Override
	public int updateSysUser(SysUserUpdateReqVo updateReq) {
		SysUserBean user = new SysUserBean();
		user.setUserId(updateReq.getUserId());

		SysUserBean sysUserBean = sysUserDao.querySysUser(user);

		if (sysUserBean == null) {
			log.error("用户信息：{}不存在", updateReq);
			throw new BaseServiceException(USER_INFO_NOT_EXIST_ERROR);
		}

		BeanUtils.copyProperties(updateReq, user);
		user.setUpdatedBy("koobe");
		user.setUpdatedDate(new Date());

		return sysUserDao.updateSysUser(user);
	}

	/**
	 * 用户登录
	 *
	 * @param record 登录参数
	 * @return UserLoginResp
	 * @author 马庆智
	 * @date: 2023/3/29 16:14
	 */
	@Override
	public UserLoginRespVo login(UserLoginReqVo record) {

		SysUserBean sysUserBean = new SysUserBean();
		sysUserBean.setUserName(record.getUserName());

		SysUserBean user = sysUserDao.querySysUser(sysUserBean);
		if (user == null) {
			log.error("用户信息：{}不存在", record);
			throw new BaseServiceException(USER_INFO_NOT_EXIST_ERROR);
		}

		if (!record.getPassword().equals(user.getPassword())) {
			log.error("密码不正确");
			throw new BaseServiceException(PASSWORD_NOT_CORRECT_ERROR);
		}

		List<String> interfacePaths = this.queryMenuList(user.getUserId()).stream().map(SysMenuBean::getInterfacePath)
				.filter(Objects::nonNull).collect(Collectors.toList());
		Map<String, Object> claims = new HashMap<>();
		claims.put("userId", user.getUserId());
		claims.put("userName", user.getUserName());
		claims.put("permissions", interfacePaths);
		String token = Jwts.builder().setClaims(claims).setExpiration(new Date(System.currentTimeMillis() + 243600_000))
				.signWith(SignatureAlgorithm.HS512, baseConfig.jwtSecretKey).compact();

		UserLoginRespVo loginResp = new UserLoginRespVo();
		loginResp.setUserId(user.getUserId());
		loginResp.setUserName(user.getUserName());
		loginResp.setNickName(user.getNickName());
		loginResp.setToken(token);

		return loginResp;
	}

	/**
	 * 查询用户菜单
	 *
	 * @param userId 用户id
	 * @return SysUserResp
	 * @author 马庆智
	 * @date: 2023/3/29 17:14
	 */
	@Override
	public UserMenuResp queryUserMenuList(Integer userId) {

		List<String> btnPaths = this.queryMenuList(userId).stream()
				.filter(x -> x.getStatus().equals(StatusEnum.enable.getCode()))
				.filter(x -> x.getMenuType().equals(MenuTypeEnum.button.getCode()) && x.getInterfacePath() != null)
				.map(SysMenuBean::getInterfacePath).filter(x -> !x.isEmpty()).collect(Collectors.toList());

		List<UserMenuDataVo> userMenuData = this.queryMenuList(userId).stream()
				.filter(x -> x.getStatus().equals(StatusEnum.enable.getCode()))
				.filter(x -> !(x.getMenuType().equals(MenuTypeEnum.button.getCode()))).map(x -> {
					UserMenuDataVo menuData = UserMenuDataVo.builder().build();
					BeanUtils.copyProperties(x, menuData);
					return menuData;
				}).collect(Collectors.toList());

		return UserMenuResp.builder().btnPaths(btnPaths).menuData(userMenuData).build();

	}

	/**
	 * 查询用户所有菜单
	 *
	 * @param userId 用户id
	 * @return
	 * @author 马庆智
	 * @date: 2023/3/30 16:04
	 */
	private List<SysMenuBean> queryMenuList(Integer userId) {
		List<SysUserRoleRespVo> userRoleList = userRoleBiz.querySysUserRoleList(
				SysUserRoleListReqVo.builder().userId(userId).build());

		boolean b = userRoleList.stream().noneMatch(x -> BaseConstant.ADMIN_ROLE_ID.equals(x.getRoleId()));

		//return count > 0 ? menuService.querySysMenuListBean().stream().map(x -> {
		//	UserMenuResp menuResp = UserMenuResp.builder().build();
		//	BeanUtils.copyProperties(x, menuResp);
		//	return menuResp;
		//}).collect(Collectors.toList()) : sysUserDao.queryUserMenus(userId).stream().map(x -> {
		//	UserMenuResp menuResp = UserMenuResp.builder().build();
		//	BeanUtils.copyProperties(x, menuResp);
		//	return menuResp;
		//}).collect(Collectors.toList());
		return b ? sysUserDao.queryUserMenus(userId) : menuBiz.querySysMenuListBean();
	}

	/**
	 * 用户角色
	 *
	 * @param userId 用户id
	 * @return List<UserRoleResp>
	 * @author 马庆智
	 * @date: 2023/3/30 9:21
	 */
	@Override
	public UserRoleResp queryUserRoleList(Integer userId) {

		List<SysRoleRespVo> userRoleList = sysUserDao.queryUserRoles(userId).stream().map(this::buildRoleResp)
				.collect(Collectors.toList());

		List<Integer> userRoleIds = userRoleList.stream().map(SysRoleRespVo::getRoleId).collect(Collectors.toList());

		List<SysRoleRespVo> allRoleList = roleBiz.querySysRoleList(
				SysRoleListReqVo.builder().current(1).pageSize(1000).build()).getList();

		return UserRoleResp.builder().roleIds(userRoleIds).allRoleList(allRoleList).userRoleList(userRoleList).build();
	}

	/**
	 * 构建角色返回
	 *
	 * @param sysRoleBean db
	 * @return SysRoleResp vo
	 * @author 马庆智
	 * @date: 2023/3/30 10:22
	 */
	private SysRoleRespVo buildRoleResp(SysRoleBean sysRoleBean) {
		SysRoleRespVo roleResp = SysRoleRespVo.builder().build();
		BeanUtils.copyProperties(sysRoleBean, roleResp);
		return roleResp;
	}

	/**
	 * 分配用户角色
	 *
	 * @param record 请求参数
	 * @return SysUserResp
	 * @author 马庆智
	 * @date: 2023/3/30 9:18
	 */
	@Override
	public Integer saveUserRoleList(SaveUserRoleListReqVo record) {
		Integer userId = record.getUserId();
		List<Integer> roleIds = record.getRoleIds();

		userRoleBiz.deleteSysUserRole(userId);

		for (Integer roleId : roleIds) {
			userRoleBiz.saveSysUserRole(SysUserRoleAddReqVo.builder().userId(userId).roleId(roleId).build());
		}

		return roleIds.size();
	}
}